package com.xiaoq.coms.util;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.springframework.util.Assert;

public class AesUtil {
	private static final String UTF8 = "UTF-8";
	private static final String AES = "AES";
	private static final String KEY_SPEC = "AES/ECB/PKCS5Padding";
	
	public static byte[] encrypt(byte[] content, byte[] password) {
		return doCipher(content, password, Cipher.ENCRYPT_MODE);
	}
	
	public static byte[] encrypt(byte[] content, String password) {
		return doCipher(content, password.getBytes(), Cipher.ENCRYPT_MODE);
	}
	
	public static String encrypt2Hex(byte[] content, byte[] password) {
		return HexUtil.hex(doCipher(content, password, Cipher.ENCRYPT_MODE));
	}
	
	public static String encrypt2Hex(byte[] content, String password) {
		return HexUtil.hex(doCipher(content, password.getBytes(), Cipher.ENCRYPT_MODE));
	}
	
	public static String encrypt2Base64(byte[] content, byte[] password) {
		return Base64.encodeBase64String(doCipher(content, password, Cipher.ENCRYPT_MODE));
	}
	
	public static String encrypt2Base64(byte[] content, String password) {
		return Base64.encodeBase64String(doCipher(content, password.getBytes(), Cipher.ENCRYPT_MODE));
	}
	
	public static byte[] encrypt(String content, byte[] password) {
		try {
			return doCipher(content.getBytes(UTF8), password, Cipher.ENCRYPT_MODE);
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}
	
	public static byte[] encrypt(String content, String password) {
		return encrypt(content, password.getBytes());
	}
	
	public static String encrypt2Hex(String content, byte[] password) {
		return HexUtil.hex(encrypt(content, password));
	}
	
	public static String encrypt2Hex(String content, String password) {
		return HexUtil.hex(encrypt(content, password));
	}
	
	public static String encrypt2Base64(String content, byte[] password) {
		return Base64.encodeBase64String(encrypt(content, password));
	}
	
	public static String encrypt2Base64(String content, String password) {
		return Base64.encodeBase64String(encrypt(content, password));
	}

	public static byte[] decrypt(byte[] content, byte[] password) {
		return doCipher(content, password, Cipher.DECRYPT_MODE);
	}
	
	public static byte[] decrypt(byte[] content, String password) {
		return doCipher(content, password.getBytes(), Cipher.DECRYPT_MODE);
	}
	
	public static String decrypt2String(byte[] content, byte[] password) {
		try {
			return new String(decrypt(content, password), UTF8);
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}
	
	public static String decrypt2String(byte[] content, String password) {
		try {
			return new String(decrypt(content, password), UTF8);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return "";
		}
	}
	
	public static String decrypt2Hex(byte[] content, byte[] password) {
		return HexUtil.hex(doCipher(content, password, Cipher.DECRYPT_MODE));
	}
	
	public static String decrypt2Hex(byte[] content, String password) {
		return HexUtil.hex(doCipher(content, password.getBytes(), Cipher.DECRYPT_MODE));
	}
	
	public static String decrypt2Base64(byte[] content, byte[] password) {
		return Base64.encodeBase64String(decrypt(content, password));
	}
	
	public static String decrypt2Base64(byte[] content, String password) {
		return Base64.encodeBase64String(decrypt(content, password));
	}
	
	public static byte[] decrypt(String content, byte[] password) {
		try {
			return doCipher(content.getBytes(UTF8), password, Cipher.DECRYPT_MODE);
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}
	
	public static byte[] decrypt(String content, String password) {
		try {
			return doCipher(content.getBytes(UTF8), password.getBytes(), Cipher.DECRYPT_MODE);
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}

	public static String decrypt2Hex(String content, byte[] password) {
		return HexUtil.hex(decrypt(content, password));
	}
	
	public static String decrypt2Hex(String content, String password) {
		return HexUtil.hex(decrypt(content, password));
	}
	
	public static String decrypt2Base64(String content, byte[] password) {
		return Base64.encodeBase64String(decrypt(content, password));
	}
	
	public static String decrypt2Base64(String content, String password) {
		return Base64.encodeBase64String(decrypt(content, password));
	}
	
	public static String decrypt2String(String content, byte[] password) {
		try {
			return new String(decrypt(content, password), UTF8);
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}

	public static String decrypt2String(String content, String password) {
		try {
			return new String(decrypt(content, password), UTF8);
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}
	
	public static byte[] doCipher(byte[] content, byte[] password, int mode) {
		try {
			SecretKeySpec key = new SecretKeySpec(password, AES);
			Cipher cipher = Cipher.getInstance(KEY_SPEC);
			cipher.init(mode, key);
			byte[] result = cipher.doFinal(content);
			return result;
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static void main(String[] args) {
		String content = "root";
		String password = "12345678abcdefgh";
		
		byte[] encryptResult = encrypt(content, password);
		String a = Base64.encodeBase64String(encryptResult);
		String deContent = decrypt2String(encryptResult, password);
		System.out.println(deContent);
		System.out.println(a);
		String b = encrypt2Base64(content, password);
		Assert.isTrue(a.equals(b), "");
		
		a = HexUtil.hex(encryptResult);
		b = encrypt2Hex(content, password);
		Assert.isTrue(a.equals(b), "");
		
		
		byte[] decryptResult = decrypt(encryptResult, password);
		a = Base64.encodeBase64String(decryptResult);
		System.out.println(a);
		b = decrypt2Base64(encryptResult, password);
		Assert.isTrue(a.equals(b), "");
		
		a = HexUtil.hex(decryptResult);
		b = decrypt2Hex(encryptResult, password);
		Assert.isTrue(a.equals(b), "");
		
		
		
	}
}